/* Polynom.h header file
   ---------------------
   Specifies Polynom class methods implementation
 */

#include <iostream>
#include "Monom.h"
#include "Polynom.h"

using namespace std;


// Polynom/Monom + Polynom/Monom
Polynom operator+(const Polynom &p1, const Polynom &p2)
{

    // Create temp polynom object
    Polynom p3(p2);
    
	// Add p1 monom's to p2
    for (int n=p1.poly.Size(),i=0;i<n;i++)
		p3.poly.PushBack(*(p1.poly[i]));

	p3.poly.Sort();

    // Look for consecutive Monom exponents and join them together
	for (int j=1;j<p3.poly.Size();j++)
	{
		// Same exponent
		if (p3.poly[j-1]->getExponent() == p3.poly[j]->getExponent())
		{
			p3.poly[j-1]->setC(p3.poly[j-1]->getC() + p3.poly[j]->getC());
			p3.poly.Remove(*(p3.poly[j]));
    	}
	}

	// Omit all redundant zero's if exist
    if (p3.poly.Size() > 1 && p3.poly.Exists(0))
        p3.poly.Remove(0);

	return p3;  
}


// Polynom/Monom - Polynom/Monom
Polynom operator-(const Polynom &p1, const Polynom &p2)
{
    Polynom p(p2);
    p.allMinus();
    return (p1+p);
}


// Copy Constructor for Polynom
Polynom::Polynom(const Polynom &p)
{
	int n = p.poly.Size();
	for (int i=0;i<n;i++)
		this->poly.PushBack(*(p.poly[i]));
}

// Assignment operator= copy all nodes from p --> this
const Polynom& Polynom::operator=(const Polynom &p)
{
	// Self assignment protection
	if (this == &p)
		return *this;

	// Remove all current nodes
	this->poly.Clear();

	// Copy polynom p to this
	int n = p.poly.Size();
	for (int i=0;i<n;i++)
		this->poly.PushBack(*(p.poly[i]));

	return *this;
}


// Derives polynom & returns reference to *this
const Polynom& Polynom::derive()
{
	// Derive all monoms in list
	for (int i=0;i<poly.Size();i++)
		poly[i]->derive();

	// Remove redundant zero's in polynom
	if (poly.Size() > 1)
		poly.Remove(0);

	return *this;
}

// Performs C*= -1 on all monoms
void Polynom::allMinus()
{
	int size=this->poly.Size();
	for (int i=0;i<size;i++)
			*(this->poly[i])*=-1;
}
